<template>
  <div ref="container" style="width: 100%; height: 600px;"></div>
</template>

<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { FontLoader } from 'three/examples/jsm/loaders/FontLoader';
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry';

export default {
  name: 'Beamforming3DChart',
  mounted() {
    this.initThreeJS();
  },
  methods: {
    initThreeJS() {
      // 创建场景
      const scene = new THREE.Scene();

      // 创建相机
      const camera = new THREE.PerspectiveCamera(75, this.$refs.container.clientWidth / this.$refs.container.clientHeight, 0.1, 1000);
      camera.position.x = 1;
      camera.position.y = 2;
      camera.position.z = 3;

      // 创建渲染器
      const renderer = new THREE.WebGLRenderer({ antialias: true });
      renderer.setSize(this.$refs.container.clientWidth, this.$refs.container.clientHeight);
      renderer.setClearColor(0xffffff); // 设置背景为白色
      this.$refs.container.appendChild(renderer.domElement);

      // 添加方向轴
      const axesHelper = new THREE.AxesHelper(2); // 轴的长度为2
      scene.add(axesHelper);

      // 添加刻度线和文本
      const tickMaterial = new THREE.LineBasicMaterial({ color: 0x000000 });
      const fontLoader = new FontLoader();
      
      fontLoader.load('/fonts/helvetiker_regular.typeface.json', (font) => {
        // 在每个刻度位置添加文本
        for (let i = -2; i <= 2; i += 0.5) {
          if (i !== 0) {
            // X轴刻度
            const xTickGeometry = new THREE.BufferGeometry().setFromPoints([
              new THREE.Vector3(i, -0.05, 0),
              new THREE.Vector3(i, 0.05, 0)
            ]);
            const xTick = new THREE.Line(xTickGeometry, tickMaterial);
            scene.add(xTick);

            // Y轴刻度
            const yTickGeometry = new THREE.BufferGeometry().setFromPoints([
              new THREE.Vector3(-0.05, i, 0),
              new THREE.Vector3(0.05, i, 0)
            ]);
            const yTick = new THREE.Line(yTickGeometry, tickMaterial);
            scene.add(yTick);

            // Z轴刻度
            const zTickGeometry = new THREE.BufferGeometry().setFromPoints([
              new THREE.Vector3(0, -0.05, i),
              new THREE.Vector3(0, 0.05, i)
            ]);
            const zTick = new THREE.Line(zTickGeometry, tickMaterial);
            scene.add(zTick);

            // X轴刻度文本
            const xTextGeometry = new TextGeometry(i.toString(), {
              font: font,
              size: 0.1,
              depth: 0.01
            });
            const xTextMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });
            const xText = new THREE.Mesh(xTextGeometry, xTextMaterial);
            xText.position.set(i, 0.1, 0);
            scene.add(xText);

            // Y轴刻度文本
            const yTextGeometry = new TextGeometry(i.toString(), {
              font: font,
              size: 0.1,
              depth: 0.01
            });
            const yTextMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });
            const yText = new THREE.Mesh(yTextGeometry, yTextMaterial);
            yText.position.set(0.1, i, 0);
            scene.add(yText);

            // Z轴刻度文本
            const zTextGeometry = new TextGeometry(i.toString(), {
              font: font,
              size: 0.1,
              depth: 0.01
            });
            const zTextMaterial = new THREE.MeshBasicMaterial({ color: 0x000000 });
            const zText = new THREE.Mesh(zTextGeometry, zTextMaterial);
            zText.position.set(0, 0.1, i);
            scene.add(zText);
          }
        }
      });

      // 创建波束数据
      const data = this.generateBeamformingData(16, 16);

      // 创建几何体
      const geometry = new THREE.BufferGeometry();
      const vertices = [];
      const colors = [];

      data.forEach(point => {
        vertices.push(point[0], point[1], point[2]);
        const color = new THREE.Color(0x00aaff);
        color.setHSL(0.6, 1.0, 0.5 * (point[2] + 1));
        colors.push(color.r, color.g, color.b);
      });

      geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));
      geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));

      // 创建材质
      const material = new THREE.PointsMaterial({ vertexColors: true, size: 0.1 });

      // 创建点云
      const points = new THREE.Points(geometry, material);
      scene.add(points);

      // 添加光源
      const light = new THREE.DirectionalLight(0xffffff, 1);
      light.position.set(1, 1, 1).normalize();
      scene.add(light);

      // 添加轨道控制器（支持鼠标拖动旋转）
      const controls = new OrbitControls(camera, renderer.domElement);
      controls.enableDamping = true; // 启用阻尼效果，使旋转更平滑
      controls.dampingFactor = 0.05; // 阻尼系数

      // 渲染函数
      const render = () => {
        requestAnimationFrame(render);
        controls.update(); // 更新控制器
        renderer.render(scene, camera);
      };

      render();
    },

    generateBeamformingData(rows, cols) {
      const data = [];
      const numTheta = 180; // 仰角：从 0° 到 180°
      const numPhi = 360; // 方位角：从 0° 到 360°
      const d = 0.1; // 天线间距（适当加大，让波束更饱满）
      const k = 2 * Math.PI; // 波数
      const beamAngleTheta = Math.PI / 3; // 主波束方向（仰角）
      const beamAnglePhi = Math.PI / 6; // 主波束方向（方位角）

      // 计算方向性增强后的波束
      for (let theta = 0; theta <= numTheta; theta++) {
        for (let phi = 0; phi < numPhi; phi++) {
          const thetaRad = (theta / numTheta) * Math.PI; // 仰角弧度
          const phiRad = (phi / numPhi) * 2 * Math.PI; // 方位角弧度

          // 计算方向向量
          const dx = Math.sin(thetaRad) * Math.cos(phiRad);
          const dy = Math.sin(thetaRad) * Math.sin(phiRad);
          const dz = Math.cos(thetaRad);

          // 波束方向性函数
          let arrayFactor = 0;
          for (let m = 0; m < rows; m++) {
            for (let n = 0; n < cols; n++) {
              const deltaX = m * d; // 水平方向相位差
              const deltaY = n * d; // 垂直方向相位差
              const phaseShift =
                k *
                (deltaX * (dx - Math.sin(beamAngleTheta) * Math.cos(beamAnglePhi)) +
                  deltaY * (dy - Math.sin(beamAngleTheta) * Math.sin(beamAnglePhi)));
              arrayFactor += Math.cos(phaseShift);
            }
          }

          // 强度归一化，增强主瓣
          const intensity = Math.pow(Math.abs(arrayFactor) / (rows * cols), 2);

          // 转为笛卡尔坐标，适当放大波束范围
          const scale = 1; // 放大比例
          const x = scale * intensity * Math.sin(thetaRad) * Math.cos(phiRad);
          const y = scale * intensity * Math.sin(thetaRad) * Math.sin(phiRad);
          const z = scale * intensity * Math.cos(thetaRad);

          data.push([x, y, z]);
        }
      }

      return data;
    },
  },
};
</script>

<style scoped>
/* 样式部分 */
</style>
